#include "fatfs_app.h"

#include "cmsis_os2.h"

/* FatFs includes component */
#include "ff_gen_drv.h"
#include "sd_diskio.h"

#include "logs.h"

/* sd card fatfs info */
FATFS SDFatFs;  /* File system object for SD card logical drive */
FATFS SPI_Flash_FatFs;  /* File system object for SPI flash logical drive */
FIL MyFile;     /* File object */
FIL MyFile_spi_flash;     /* File object */
char SDPath [4]; /* SD card logical drive path */
char spi_flash_path [4]; /* spi flash logical drive path */
static uint8_t buffer[_MAX_SS]; /* a work buffer for the f_mkfs() */

void sd_fatfs_init(void)
{
    FRESULT res = FR_OK;                                          /* FatFs function common result code */
    uint32_t byteswritten , bytesread;                     /* File write/read counts */
    const uint8_t wtext[] = "tom port fatfs to stm32u575 ok."; /* File write buffer */
    uint8_t rtext [100];                                   /* File read buffer */

    /*##-1- Link the micro SD disk I/O driver ##################################*/
    if (0 != FATFS_LinkDriverEx(&SD_Driver , SDPath, SD_CARD_VOLUME)) {
        res = FR_INT_ERR;
        goto sd_fatfs_init_fail;
    } else {
        logs_i("success link sd driver,path:%s", SDPath);
    }

    /*##-2- Register the file system object to the FatFs module ##############*/
    res = f_mount(&SDFatFs , ( TCHAR const* ) SDPath , 1); // mount sd fatfs right now
    if ( res != FR_OK ) {
        /* FatFs Initialization Error */
        logs_e("mount sd fail, res:%d.", res);
        res = FR_DISK_ERR;
        goto sd_fatfs_init_fail;
    } else {
        logs_i("success mount sd fatfs,path:%s", SDPath);
    }

#if SDCARD_FORMAT_WHEN_INIT
    /*##-3- Create a FAT file system (format) on the logical drive #########*/
    /* WARNING: Formatting the uSD card will delete all content on the device */
    res = f_mkfs(( TCHAR const* ) SDPath , FM_FAT , 0, buffer , sizeof(buffer));
    if ( res != FR_OK ) {
        goto sd_fatfs_init_fail;
    }
#endif

    /*##-4- Create and Open a new text file object with write access #####*/
    res= f_open(&MyFile , SDCARD_NEW_FILE_NAME, FA_READ);
    if ( res != FR_OK ) {
        logs_e("f_open fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    }

#if SDCARD_TEST_WRITE_FILE
    /*##-5- Write data to the text file ################################*/
    res = f_write(&MyFile , wtext , strlen((const char*)wtext) , ( void * ) &byteswritten);
    if ( (byteswritten == 0) || (res != FR_OK) ) {
        logs_e("f_write fail, byteswritten:%d, res:%d.", byteswritten, res);
        goto sd_fatfs_init_fail;
    }
#endif

    /* test read text from file */
    res = f_read(&MyFile , rtext , sizeof(rtext) , ( void * ) &bytesread);
    if ( (bytesread == 0) || (res != FR_OK) ) {
        logs_i("f_read fail, bytesread:%d, res:%d.", bytesread, res);
        goto sd_fatfs_init_fail;
    } else {
        rtext[bytesread] = '\0';
        logs_i("f_read ok,bytesread:%d.", bytesread);
        logs_i("f_read ok,read:%s", rtext);
    }

    /*##-6- Close the open text file #################################*/
    res = f_close(&MyFile);
    if ( res != FR_OK ) {
        logs_e("f_close fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    }

    /*##-a- Link the micro spi flash disk I/O driver ##################################*/
    if (0 != FATFS_LinkDriverEx(&SD_Driver , spi_flash_path, SPI_FLASH_VOLUME)) {
        res = FR_INT_ERR;
        goto sd_fatfs_init_fail;
    } else {
        logs_i("success link spi flash driver,path:%s.", spi_flash_path);
    }

#if SPI_FLASH_FORMAT_WHEN_INIT
    res = f_mkfs(( TCHAR const* ) spi_flash_path , FM_ANY , 0 , buffer, sizeof(buffer));
    if ( res != FR_OK ) {
        /* FatFs Initialization Error */
        logs_e("format spi flash fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    } else {
        logs_i("success format spi flash,path:%s", spi_flash_path);
    }
#endif

    /*##-b- Register the file system object to the FatFs module ##############*/
    res = f_mount(&SPI_Flash_FatFs, ( TCHAR const* ) spi_flash_path, 1);
    if ( res != FR_OK ) {
        /* FatFs Initialization Error */
        logs_e("mount spi flash fail, res:%d.", res);
        res = FR_DISK_ERR;
        goto sd_fatfs_init_fail;
    } else {
        logs_i("success mount spi flash driver,path:%s.", spi_flash_path);
    }

#if SPI_FLASH_TEST_WRITE_FILE
    /*##-d- Create and Open a new text file object with write access #####*/
    res= f_open(&MyFile_spi_flash , SPI_FLASH_NEW_FILE_NAME, FA_READ | FA_WRITE | FA_CREATE_NEW);
    if ( res != FR_OK ) {
        logs_e("spi flash f_open fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    }

    /*##-e- Write data to the text file ################################*/
    res = f_write(&MyFile_spi_flash , "hello spi flash fatfs." , strlen((const char*)"hello spi flash fatfs.") , ( void * ) &byteswritten);
    if ( (byteswritten == 0) || (res != FR_OK) ) {
        logs_e("spi flash f_write fail, byteswritten:%d, res:%d.", byteswritten, res);
        goto sd_fatfs_init_fail;
    }

    /*##-f- Close the open text file #################################*/
    res = f_close(&MyFile_spi_flash);
    if ( res != FR_OK ) {
        logs_e("spi flash f_close fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    }
#endif

    /*##-g- Open the text file object with read access ########################*/
    res= f_open(&MyFile_spi_flash , SPI_FLASH_NEW_FILE_NAME, FA_READ);
    if ( res != FR_OK ) {
        logs_e("spi flash f_open fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    }

    /*##-h- Read data from the text file ################################*/
    res = f_read(&MyFile_spi_flash , rtext , sizeof(rtext) , ( void * ) &bytesread);
    if ( (bytesread == 0) || (res != FR_OK) ) {
        logs_e("spi flash f_read fail, bytesread:%d, res:%d.", bytesread, res);
        goto sd_fatfs_init_fail;
    } else {
        logs_i("spi flash f_read ok,bytesread:%d.", bytesread);
        for (int i = 0; i < bytesread; i++) {
            printf("%c", rtext[i]);
        }
        printf("\r\n");
    }

    /*##-i- Close the open text file #################################*/
    res = f_close(&MyFile_spi_flash);
    if ( res != FR_OK ) {
        logs_e("spi flash f_close fail, res:%d.", res);
        goto sd_fatfs_init_fail;
    }

    logs_i("fatfs_init all done, ok.");

    return;

sd_fatfs_init_fail:
    logs_e("sd_fatfs_init fail, res:%d.", res);
}
